package com.javajun.custom;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.databind.ObjectMapper;


public class JqGridParm {

	private String nd;// 随机nd
	private Integer page;// 页号
	private Integer rows;// 表格行数，即一页数据数
	private Boolean search = false;// 是否筛选
	private String sidx;// 排序字段
	private String sord;// 排序方式
	private String searchField;
	private String searchOper;
	private String searchString;
	private String filters;
	
	public Pageable buildPageable() {
		// page-- 是因为Spring中的pageable对象的页码是从0开始的
		page--;
		// 排序规则
		Sort sort = Sort.by(Direction.fromString(sord), sidx);
		// page表示第几页即当前页号，rows表示多少挑数据，sort表示排序规则
		return PageRequest.of(page, rows, sort);
	}
	
	public void split(String str,List<String> list) {
		if(str.contains(",")||str.contains("，")) {
			if(str.contains(",")) {
				String[] s=StringUtils.split(str, ",");
				list.add(s[0]);
				split(s[1], list);
			}
			if(str.contains("，")) {
				String[] s=StringUtils.split(str, "，");
				list.add(s[0]);
				split(s[1], list);
				
			}
		}else {
			list.add(str);
		}
		
	}
	
	public Specification buildSpec() {
		Specification spec=new Specification() {

			@Override
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
				List<Predicate> rules= new ArrayList<>();
				Predicate predicate=null;
				if(!StringUtils.hasText(filters)) {
					Expression exp=root.get(searchField);
					if ("eq".equals(searchOper)) {
						predicate= cb.equal(exp, searchString);
					}
					if("ne".equals(searchOper)) {
						predicate= cb.notEqual(exp, searchString);
					}
					if("lt".equals(searchOper)) {
						predicate= cb.lessThan(exp, searchString);
					}
					if("le".equals(searchOper)) {
						predicate= cb.lessThanOrEqualTo(exp, searchString);
					}
					if("gt".equals(searchOper)) {
						predicate= cb.greaterThan(exp, searchString);
					}
					if("ge".equals(searchOper)) {
						predicate= cb.greaterThanOrEqualTo(exp, searchString);
					}
					if("bw".equals(searchOper)) {
						predicate= cb.like(exp, searchString+"%");
					}
					if("bn".equals(searchOper)) {
						predicate= cb.notLike(exp, searchString+"%");
					}
					if("in".equals(searchOper)) {
						List<String> strings=new ArrayList<>();
						split(searchString, strings);
						predicate= exp.in(strings);
					}
					if("ni".equals(searchOper)) {
						List<String> strings=new ArrayList<>();
						split(searchString, strings);
						predicate= exp.in(strings).not();
					}
					if("ew".equals(searchOper)) {
						predicate= cb.like(exp, "%"+searchString);
					}
					if("en".equals(searchOper)) {
						predicate= cb.notLike(exp, "%"+searchString);
					}
					if("cn".equals(searchOper)) {
						predicate= cb.like(exp, "%"+searchString+"%");
					}
					if("nc".equals(searchOper)) {
						predicate= cb.notLike(exp, "%"+searchString+"%");
					}
				}else {
					ObjectMapper mapper=new ObjectMapper();
					Filters filter = null;
					//System.out.println(filters);
					try {
						filter = mapper.readValue(filters, Filters.class);
					} catch (IOException e) {
						e.printStackTrace();
					}
					for (Rule multipleSearch : filter.getRules()) {
						String data = multipleSearch.getData();
						String field = multipleSearch.getField();
						String op = multipleSearch.getOp();
						Expression exp = root.get(field);
						if ("eq".equals(op)) {
							rules.add(cb.equal(root.get(field), data));
						}
						if("ne".equals(op)) {
							rules.add(cb.notEqual(exp, data));
						}
						if("lt".equals(op)) {
							rules.add(cb.lessThan(exp, data));
						}
						if("le".equals(op)) {
							rules.add(cb.lessThanOrEqualTo(exp, data));
						}
						if("gt".equals(op)) {
							rules.add(cb.greaterThan(exp, data));
						}
						if("ge".equals(op)) {
							rules.add(cb.greaterThanOrEqualTo(exp, data));
						}
						if("bw".equals(op)) {
							rules.add(cb.like(exp, data+"%"));
						}
						if("bn".equals(op)) {
							rules.add(cb.notLike(exp, data+"%"));
						}
						if("in".equals(op)) {
							List<String> strings=new ArrayList<>();
							split(data, strings);
							rules.add(exp.in(strings));
						}
						if("ni".equals(op)) {
							List<String> strings=new ArrayList<>();
							split(data, strings);
							rules.add(exp.in(strings).not());
						}
						if("ew".equals(op)) {
							rules.add(cb.like(exp, "%"+data));
						}
						if("en".equals(op)) {
							rules.add(cb.notLike(exp, "%"+data));
						}
						if("cn".equals(op)) {
							rules.add(cb.like(exp, "%"+data+"%"));
						}
						if("nc".equals(op)) {
							rules.add(cb.notLike(exp, "%"+data+"%"));
						}
					}
					if("AND".equals(filter.getGroupOp())) {
						predicate= cb.and(rules.toArray(new Predicate[rules.size()]));
					}else {
						predicate= cb.or(rules.toArray(new Predicate[rules.size()]));
					}
				}
				return predicate;
			}
		};
		return spec;
	}
	
	public String getNd() {
		return nd;
	}
	public void setNd(String nd) {
		this.nd = nd;
	}

	public Integer getPage() {
		return page;
	}
	public void setPage(Integer page) {
		this.page = page;
	}
	public Integer getRows() {
		return rows;
	}
	public void setRows(Integer rows) {
		this.rows = rows;
	}
	public Boolean getSearch() {
		return search;
	}
	public void setSearch(Boolean search) {
		this.search = search;
	}
	public String getSidx() {
		return sidx;
	}
	public void setSidx(String sidx) {
		this.sidx = sidx;
	}
	public String getSord() {
		return sord;
	}
	public void setSord(String sord) {
		this.sord = sord;
	}

	public String getSearchField() {
		return searchField;
	}

	public void setSearchField(String searchField) {
		this.searchField = searchField;
	}

	public String getSearchOper() {
		return searchOper;
	}

	public void setSearchOper(String searchOper) {
		this.searchOper = searchOper;
	}

	public String getSearchString() {
		return searchString;
	}

	public void setSearchString(String searchString) {
		this.searchString = searchString;
	}

	public String getFilters() {
		return filters;
	}

	public void setFilters(String filters) {
		this.filters = filters;
	}
	
	
}
